﻿/*
 * KLF Headless Browser
 * Written by Kris Oye <kristianoye@gmail.com>
 * Copyright (C) 2011-2012.  All rights reserved.
 */
namespace KLF.Lib.Browser.DOM
{
    #region Using Statements

    using System.Text;

    #endregion

    abstract public class CharacterData : Node
    {
        #region Properties

        /// <summary>
        /// Underlying data for the character data.  Points into a string table
        /// to prevent duplication.
        /// </summary>
        internal StringLookup _data;

        /// <summary>
        /// The character data of the node that implements this interface.
        /// The DOM implementation may not put arbitrary limits on the amount
        /// of data that may be stored in a CharacterData node. However, 
        /// implementation limits may mean that the entirety of a node's data
        /// may not fit into a single DOMString. In such cases, the user may
        /// call substringData to retrieve the data in appropriately 
        /// sized pieces. 
        /// </summary>
        public string data
        {
            get
            {
                return _data.Value;
            }
            set
            {
                _data = new StringLookup(value);
            }
        }

        #endregion

        #region Constructors

        internal CharacterData()
        {
        }

        internal CharacterData(Document owner, string text)
            : base(owner)
        {
            data = text;
        }

        #endregion

        #region DOM Level 1 Compliance

        /// <summary>
        /// Append the string to the end of the character data of the node. 
        /// Upon success, data provides access to the concatenation of data
        /// and the DOMString specified.
        /// </summary>
        /// <param name="arg">The DOMString to append.</param>
        public void appendData(string arg)
        {
            data = data + arg;
        }

        /// <summary>
        /// Remove a range of characters from the node. Upon success, data and length reflect the change.
        /// </summary>
        /// <param name="offset">The offset from which to remove characters.</param>
        /// <param name="count">The number of characters to delete. If the sum of offset and count exceeds length then all characters from offset to the end of the data are deleted.</param>
        public void deleteData(int offset, int count)
        {
            data.Remove(offset, count);
        }

        /// <summary>
        /// Insert a string at the specified character offset. 
        /// </summary>
        /// <param name="offset">The character offset at which to insert.</param>
        /// <param name="arg">The DOMString to insert.</param>
        public void insertData(int offset, string arg)
        {
            data.Insert(offset, arg);
        }

        /// <summary>
        /// The number of characters that are available through data and the 
        /// substringData method below. This may have the value zero, i.e.,
        /// CharacterData nodes may be empty.
        /// </summary>
        public int length { get { return data.Length; } }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="offset">The offset from which to start replacing.</param>
        /// <param name="count">The number of characters to replace. If the sum of offset and count exceeds length, then all characters to the end of the data are replaced (i.e., the effect is the same as a remove method call with the same range, followed by an append method invocation).</param>
        /// <param name="arg">The DOMString with which the range must be replaced.</param>
        public void replaceData(int offset, int count, string arg)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(data.Substring(0, offset));
            sb.Append(arg);
            sb.Append(data.Substring(offset + count));

            data = sb.ToString();
        }

        /// <summary>
        /// Extracts a range of data from the node. 
        /// </summary>
        /// <param name="offset">Start offset of substring to extract.</param>
        /// <param name="count">The number of characters to extract.</param>
        /// <returns>The specified substring. If the sum of offset and count exceeds the length, then all characters to the end of the data are returned.</returns>
        public string substringData(int offset, int count)
        {
            return data.Substring(offset, count);
        }

        #endregion
    }
}
